package com.kust.smarthome.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kust.smarthome.web.common.exception.XRKException;
import com.kust.smarthome.web.model.EmailCode;
import com.kust.smarthome.web.model.User;
import com.kust.smarthome.web.service.IEmailCodeService;
import com.kust.smarthome.web.service.IUserService;
import com.kust.smarthome.web.utils.EmailUtils;
import com.kust.smarthome.web.vo.EmailCodeVo;
import com.kust.smarthome.web.vo.RegisterVo;
import com.kust.smarthome.web.vo.UpdatePasswordVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.MessagingException;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@RestController
@Slf4j
@Api(value = "系统相关操作", tags = {"sys-tag"})
public class SystemController {

    @Autowired
    private IUserService userService;

    @Autowired
    private IEmailCodeService emailCodeService;

    @Autowired
    private EmailUtils emailUtils;

    @PostMapping("/register")
    @ApiOperation(value = "注册操作")
    //@Validated表示激活紧随其后的类型的SpringValidation验证
    //要验证的对象参数后面新增一个参数类型为BindingResult
    //SpringValidation会将验证结果自动赋值到这个对象中
    public String registerStudent(
            @Validated RegisterVo registerVo,
            BindingResult result) {
        //第二个参数registerVo会自动赋值到第一个参数中的{}的位置
        log.debug("获得用户填写的信息:{}", registerVo);

        //判断result对象中有没有错误
        if (result.hasErrors()) {
            //如果有错误,进入if语句处理
            //获得错误消息
            String msg = result.getFieldError().getDefaultMessage();
            return msg;
        }

        return userService.register(registerVo);
    }


    @PostMapping("/email")
    @ApiOperation("异步请求发送验证码")
    public boolean emailCheck(String email) throws GeneralSecurityException, MessagingException, XRKException {
        if (email == null) {
            return false;
        }

        User u = userService.getByUsername(email);
        if (u != null)
            return true;

        String code = UUID.randomUUID().toString().replace("-", "");

        QueryWrapper<EmailCode> query = new QueryWrapper<>();
        query.eq("email", email);
        EmailCode e = emailCodeService.getOne(query);
        if (e != null)
            emailCodeService.removeById(e.getId());

        EmailCode emailCode = new EmailCode()
                .setCode(code)
                .setEmail(email)
                .setState(0);
        emailCodeService.save(emailCode);
        String url = "http://xiangrikui.vaiwan.com/emailCode?" +
                "id=" + emailCode.getId() +
                "&code=" + code;

        emailUtils.sendEmail(email, "用户注册验证", url);
        return true;
    }

    @GetMapping("/emailCode")
    @ApiOperation("验证链接")
    public String emailCode(@Validated EmailCodeVo emailCodeVo, BindingResult result) {

        if (result.hasErrors()) {
            log.error(result.getFieldError().getDefaultMessage());
            return "系统错误!";
        }

        EmailCode emailCode = emailCodeService.getById(emailCodeVo.getId());
        emailCode.setState(1);
        if (emailCodeService.updateById(emailCode))
            return "更新成功!";

        return "更新失败!";

    }

    @PostMapping("/appRegister")
    @ApiOperation("app注册")
    public String appRegister(
            @Validated RegisterVo registerVo,
            BindingResult result) throws GeneralSecurityException, MessagingException {
        //判断result对象中有没有错误
        if (result.hasErrors()) {
            //如果有错误,进入if语句处理
            //获得错误消息
            return result.getFieldError().getDefaultMessage();
        }

        return userService.appRegister(registerVo);
    }

    @GetMapping("/appCode")
    @ApiOperation("用户激活")
    public String appCode(@Validated EmailCodeVo emailCodeVo, BindingResult result) {

        if (result.hasErrors())
            return "系统错误";

        EmailCode emailCode = emailCodeService.getById(emailCodeVo.getId());
        if (!emailCode.getCode().equals(emailCodeVo.getCode()))
            return "系统错误!";

        return userService.appCode(emailCode);

    }


    @PostMapping("/updatePassword")
    @ApiOperation("修改密码")
    @Transactional
    public String updatePassword(Principal principal, UpdatePasswordVo updatePasswordVo) {

        User user = userService.getByUsername(principal.getName());

        PasswordEncoder encoder = new BCryptPasswordEncoder();

        boolean b = encoder.matches(updatePasswordVo.getOldPassword(), user.getPassword());

        if (!b) {
            return "密码错误";
        }

        if (!updatePasswordVo.getNewPassword1().equals(updatePasswordVo.getNewPassword2())) {
            return "新密码不一致";
        }

        user.setPassword(encoder.encode(updatePasswordVo.getNewPassword1()));

        return "成功!";

    }

    /*@PostMapping("/getPassword4CheckEmail")
    @ApiOperation("找回密码之通过邮箱验证用户是否存在")
    public synchronized boolean getPassword(String email) throws XRKException, GeneralSecurityException, MessagingException {
        if (email == null)
            throw new XRKException("邮箱不能为空");

        User user = userService.getByUsername(email);
        if (user == null)
            throw new XRKException("用户不存在");

        EMAIL = new StringBuffer(email);
        EmailUtils emailUtils = new EmailUtils();
        code = new StringBuffer(emailUtils.sendEmail(email));

        return true;
    }*/

    /*@PostMapping("/getPassword")
    @ApiOperation("找回密码")
    public synchronized String getPassword(@Validated GetPasswordVo getPasswordVo, BindingResult result) {

        if (result.hasErrors()) {
            return result.getFieldError().getDefaultMessage();
        }

        if (!getPasswordVo.getPassword1().equals(getPasswordVo.getPassword2())) {
            return "密码不一致";
        }

        if (!code.equals(getPasswordVo.getCode()))
            return "验证码输入错误";

        if (!EMAIL.equals(getPasswordVo.getEmail()))
            return "邮箱验证异常";

        User user = userService.getByUsername(getPasswordVo.getEmail());

        PasswordEncoder encoder = new BCryptPasswordEncoder();
        user.setPassword(encoder.encode(getPasswordVo.getPassword1()));

        if (userService.updateById(user)) {
            EMAIL = null;
            code = null;
            return "ok";
        }

        return "找回密码失败";
    }*/


    @PostMapping("/upload/image")
    @ApiOperation("上传图片,返回图片路径")
    private String uploadFile(MultipartFile imageFile) throws IOException {

        String path = DateTimeFormatter.ofPattern("yyyy/MM/dd").format(LocalDate.now());

        File folder = new File("D:\\upload", path);
        folder.mkdirs();//在resourcePath路径+Path路径创建文件夹

        String fileName = imageFile.getOriginalFilename();//得到图片源文件名

        String ext = fileName.substring(fileName.lastIndexOf("."));//得到后缀名

        String name = UUID.randomUUID().toString() + ext;

        File file = new File(folder, name);
//        imageFile.transferTo(file);
        FileUtils.copyInputStreamToFile(imageFile.getInputStream(), file);

        String url = "http://xiangrikui.resource.vaiwan.com" + "/" + path + "/" + name;

        return url;

    }


}
